#include "../Include/DictProducer.h"
#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <cctype>
#include <fstream>
#include <sstream>

using std::cout;
using std::endl;
using std::ifstream;
using std::ofstream;
using std::istringstream;

DictProducer::DictProducer(const string &dir)
: _splitTool(nullptr)
{
    readDir(dir);
}

DictProducer::DictProducer(const string &dir, SplitTool *splitTool)
: _splitTool(splitTool)
{
    readDir(dir);
}

DictProducer::~DictProducer()
{

}

void DictProducer::buildEnDict()
{
    readEnFile(_files[_files.size() - 1]);

    for(auto & i : _mdict)
    {
        _dict.push_back(std::make_pair(i.first, i.second));
    }
}

void DictProducer::buildCnDict()
{
    readCnFile(_files[_files.size() - 1]);

    for(auto & i : _mdict)
    {
        _dict.push_back(make_pair(i.first, i.second));
    }
}

void DictProducer::storeDict(const char * Dictfilepath, const char * Idxfilepath)
{
    ofstream ofs1(Dictfilepath);
    if(!ofs1)
    {
        perror("ofstream");
        return;
    }
    for(auto &i : _dict)
    {
        ofs1 << i.first << " : " << i.second << endl;
    }

    ofstream ofs2(Idxfilepath);
    if(!ofs2)
    {
        perror("ofstream");
        return;
    }
    for(auto &i : _index)
    {
        ofs2 << i.first << " :";   
        for(auto & j : i.second)
        {
            ofs2 << " " << j;
        }
        ofs2 << endl;
    }
}

void DictProducer::showFiles() const
{
    for(auto i = 0; i < _files.size(); ++i)
    {
        cout << _files[i] << endl;
    }
}

void DictProducer::showDict() const
{
    for(auto & i : _dict)
    {
        cout << i.first << " : " << i.second << endl;
    }

    for(auto & i : _index)
    {
        cout << i.first << " : ";
        for(auto & j : i.second)
        {
            cout << j << "  ";
        }
        cout << endl;
    }
}

void DictProducer::mergeTXT(const string &filepath)
{
    ofstream ofs(filepath);
    if(!ofs)
    {
        perror("ofstream");
        return;
    }

    for(auto & i : _files)
    {
        ifstream ifs(i);
        if(!ifs)
        {
            perror("ifstream");
            return;
        }
        string line;
        while(getline(ifs, line))
        {
            ofs << line << endl;
        }
        ofs << endl;
        ifs.close();
    }
    ofs.close();
    _files.push_back(filepath);
}

void DictProducer::readDir(const string &dir)
{
    DIR * pdir = opendir(dir.c_str());
    if(!pdir)
    {
        perror("opendir");
    }

    struct dirent* pdirent;

    while ((pdirent = readdir(pdir)) != NULL)
    {
        if(pdirent->d_name[0] == '.')
        {
            continue;
        }

        char buff[1024];
        sprintf(buff, "%s/%s", dir.c_str(), pdirent->d_name);
        string s(pdirent->d_name);
        string s1("stop_words_eng.txt");
        string s2("stop_words_zh.txt");
        if((s == s1) || (s == s2))
        {
            readDel(buff);
            continue;
        }
        _files.push_back(buff);
    }
    closedir(pdir);
}

void DictProducer::readEnFile(const string &filepath)
{
    ifstream ifs(filepath);
    if(!ifs)
    {
        perror("ifstream");
        return;
    }

    char line[4096] = {0};
    int line_num = 0;
    while(ifs.getline(line, 4096))
    {
        ++line_num;
        const char * punct = " |``*+.,?!;:(){}[]-_/@$#%&*^~<>\"\'\\\t\n\r";
        char *tmp = strtok(line, punct);
        while(tmp)
        {
            char *p = tmp;
            while(*p){
                *p = tolower(*p);
                ++p;
            }
            if(std::find(_del.begin(), _del.end(), tmp) != _del.end())
            {
                tmp = strtok(nullptr, punct);
                continue;
            }
            for(int i = 0; tmp[i] != '\0'; ++i)
            {
                _index[string(1, tmp[i])].insert(line_num);
            }
            ++_mdict[tmp];

            tmp = strtok(nullptr, punct);
        }
    }
    ifs.close();
}

void DictProducer::readCnFile(const string &filepath)
{
    ifstream ifs(filepath);
    if(!ifs)
    {
        perror("ifstream");
        return;
    }
    string line;
    int line_num = 0;
    while(std::getline(ifs, line))
    {
        ++line_num;
        auto tmp = _splitTool->cut(line);
        for(auto & i : tmp)
        {
            if(std::find(_del.begin(), _del.end(), i) != _del.end() || i == " ")
            {
                continue;
            }
            ++_mdict[i];
            istringstream iss(i);
            char ch[4] = {0};
            while(iss.read(ch, 3))
            {

                if(std::find(_del.begin(), _del.end(), ch) != _del.end() || ch == " ")
                {
                    continue;
                }
                _index[ch].insert(line_num);
            }
        }
    }
    ifs.close();
}


void DictProducer::readDel(const string &filepath)
{
    ifstream ifs(filepath);
    if(!ifs)
    {
        perror("ifstream");
        return;
    }
    string line;
    while(ifs >> line)
    {
        _del.push_back(line);
    }
    ifs.close();
}


